﻿using System;
using System.Text;
using System.Collections.Generic;
using System.Linq;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using DDD.Core;
using FloatComparer = DDDTest.Helper.FloatComparer;

namespace DDDTest.Core {
    [TestClass]
    public class TestAnimationTrackSampling3 {
        [TestMethod]
        public void Test_Step () {
            var track = new AnimationTrack (4, 1, InterpolationType.Step);
            track.SetKeyframe (0, 0, new float[] { 0 });
            track.SetKeyframe (1, 1, new float[] { 1 });
            track.SetKeyframe (2, 2, new float[] { 2 });
            track.SetKeyframe (3, 3, new float[] { 3 });
            track.SetDuration (3);

            var value = new float[1];

            track.Sample (-1, value);
            Assert.AreEqual (0, value[0], 0.0001f);

            track.Sample (1.5f, value);
            Assert.AreEqual (1, value[0], 0.0001f);

            track.Sample (4, value);
            Assert.AreEqual (3, value[0], 0.0001f);
        }

        [TestMethod]
        public void Test_Linear () {
            var track = new AnimationTrack (4, 1, InterpolationType.Linear);
            track.SetKeyframe (0, 0, new float[] { 0 });
            track.SetKeyframe (1, 1, new float[] { 1 });
            track.SetKeyframe (2, 2, new float[] { 2 });
            track.SetKeyframe (3, 3, new float[] { 3 });
            track.SetDuration (3);

            var value = new float[1];

            track.Sample (-1, value);
            Assert.AreEqual (0, value[0], 0.0001f);

            track.Sample (1.5f, value);
            Assert.AreEqual (1.5f, value[0], 0.0001f);

            track.Sample (4, value);
            Assert.AreEqual (3, value[0], 0.0001f);
        }

        [TestMethod]
        public void Test_Spline () {
            var track = new AnimationTrack (4, 1, InterpolationType.Linear);
            track.SetKeyframe (0, 0, new float[] { 0 });
            track.SetKeyframe (1, 1, new float[] { 1 });
            track.SetKeyframe (2, 2, new float[] { 2 });
            track.SetKeyframe (3, 3, new float[] { 3 });
            track.SetDuration (3);

            var value = new float[1];

            track.Sample (0, value);
            Assert.AreEqual (0, value[0], 0.0001f);

            track.Sample (1.5f, value);
            Assert.AreEqual (1.5f, value[0], 0.0001f);

            track.Sample (3, value);
            Assert.AreEqual (3, value[0], 0.0001f);
        }

        [TestMethod]
        public void Test_Slerp () {
            var track = new AnimationTrack (2, 4, InterpolationType.Slerp);
            var q1 = new Quaternion (0, 0, 0, 1);
            var q2 = new Quaternion (90, 0, 0, 1);
            track.SetKeyframe (0, 0, (float[])q1);
            track.SetKeyframe (1, 1, (float[])q2);
            track.SetDuration (1);

            var q3 = new Quaternion (0, 0, 0, 1);
            var q4 = new Quaternion (30, 0, 0, 1);
            var q5 = new Quaternion (45, 0, 0, 1);
            var q6 = new Quaternion (90, 0, 0, 1);

            var value = new float[4];

            track.Sample (0, value);
            CollectionAssert.AreEqual ((float[])q3, value, new FloatComparer (0.0001f));

            track.Sample (0.33333f, value);
            CollectionAssert.AreEqual ((float[])q4, value, new FloatComparer (0.0001f));

            track.Sample (0.5f, value);
            CollectionAssert.AreEqual ((float[])q5, value, new FloatComparer (0.0001f));

            track.Sample (1, value);
            CollectionAssert.AreEqual ((float[])q6, value, new FloatComparer (0.0001f));
        }


        [TestMethod]
        public void Test_Loop () {
            var track = new AnimationTrack (4, 1, InterpolationType.Linear);
            track.SetKeyframe (0, 0, new float[] { 0 });
            track.SetKeyframe (1, 1, new float[] { 1 });
            track.SetKeyframe (2, 2, new float[] { 2 });
            track.SetKeyframe (3, 3, new float[] { 3 });
            track.SetDuration (3);
            track.SetLoopMode (LoopMode.Loop);

            var value = new float[1];

            track.Sample (0, value);
            Assert.AreEqual (0, value[0], 0.0001f);

            track.Sample (-1, value);
            Assert.AreEqual (2, value[0], 0.0001f);

            track.Sample (-2, value);
            Assert.AreEqual (1, value[0], 0.0001f);

            track.Sample (-3, value);
            Assert.AreEqual (0, value[0], 0.0001f);

            track.Sample (3, value);
            Assert.AreEqual (0, value[0], 0.0001f);

            track.Sample (4, value);
            Assert.AreEqual (1, value[0], 0.0001f);

            track.Sample (5, value);
            Assert.AreEqual (2, value[0], 0.0001f);

            track.Sample (6, value);
            Assert.AreEqual (3, value[0], 0.0001f);

        }

        [TestMethod]
        public void Test_AdditiveLoop () {
            var track = new AnimationTrack (4, 1, InterpolationType.Linear);
            track.SetKeyframe (0, 0, new float[] { 0 });
            track.SetKeyframe (1, 1, new float[] { 1 });
            track.SetKeyframe (2, 2, new float[] { 2 });
            track.SetKeyframe (3, 3, new float[] { 3 });
            track.SetDuration (3);
            track.SetLoopMode (LoopMode.AdditiveLoop);

            var value = new float[1];

            track.Sample (0, value);
            Assert.AreEqual (0, value[0], 0.0001f);

            track.Sample (-1, value);
            Assert.AreEqual (-1, value[0], 0.0001f);

            track.Sample (-2, value);
            Assert.AreEqual (-2, value[0], 0.0001f);

            track.Sample (-3, value);
            Assert.AreEqual (-3, value[0], 0.0001f);

            track.Sample (3, value);
            Assert.AreEqual (3, value[0], 0.0001f);

            track.Sample (4, value);
            Assert.AreEqual (4, value[0], 0.0001f);

            track.Sample (5, value);
            Assert.AreEqual (5, value[0], 0.0001f);

            track.Sample (6, value);
            Assert.AreEqual (6, value[0], 0.0001f);

        }
    }
}
